---
title: Astro에서 Markdown 사용하기
sidebar:
  label: Markdown
description: Astro의 Markdown 내장 지원에 대해 알아보세요.
i18nReady: true
---
import Since from '~/components/Since.astro';
import { FileTree } from '@astrojs/starlight/components';
import RecipeLinks from "~/components/RecipeLinks.astro";
import ReadMore from '~/components/ReadMore.astro';
import { Steps } from '@astrojs/starlight/components';

[Markdown](https://daringfireball.net/projects/markdown/)은 일반적으로 블로그 게시물 및 문서와 같이 텍스트가 많은 콘텐츠를 작성하는 데 사용됩니다. Astro에는 title, description, tags와 같은 사용자 정의 속성을 정의하기 위해 [프런트매터 YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) (또는 [TOML](https://toml.io))을 포함할 수 있는 Markdown 파일에 대한 기본 지원이 포함되어 있습니다.

Astro에서는 [GitHub Flavored Markdown](https://github.github.com/gfm/)으로 콘텐츠를 작성한 다음 `.astro` 컴포넌트에 이를 렌더링할 수 있습니다. 이는 콘텐츠용으로 설계된 친숙한 작성 형식과 Astro의 컴포넌트 구문 및 아키텍처의 유연성을 결합한 것입니다.

:::tip
Markdown에 컴포넌트 및 JSX 표현식을 포함하는 등의 추가 기능을 사용하려면 [`@astrojs/mdx` 통합](/ko/guides/integrations-guide/mdx/)을 추가하여 [MDX](https://mdxjs.com/)로 Markdown 콘텐츠를 작성하세요.
:::

## Markdown 파일 구성하기

로컬 Markdown 파일은 `src/` 디렉터리 어디에나 저장할 수 있습니다. `src/pages/`에 위치한 Markdown 파일은 자동으로 [사이트에 Markdown 페이지를 생성](#개별-markdown-페이지)합니다.

Markdown 콘텐츠와 프런트매터 속성은 [로컬 파일 가져오기](#markdown-가져오기)를 통해, 또는 [콘텐츠 컬렉션 헬퍼 함수로 가져온 데이터에서 쿼리하고 렌더링할 때](#콘텐츠-컬렉션-쿼리의-markdown) 컴포넌트에서 사용할 수 있습니다.

### 파일 가져오기 vs 콘텐츠 컬렉션 쿼리

로컬 Markdown은 단일 파일의 경우 `import` 구문을 사용하여, 여러 파일을 한 번에 가져올 때는 [Vite의 `import.meta.glob()`](/ko/guides/imports/#importmetaglob)을 사용하여 `.astro` 컴포넌트로 가져올 수 있습니다. 이렇게 [Markdown 파일에서 내보낸 데이터](#markdown-가져오기)는 `.astro` 컴포넌트에서 사용할 수 있습니다.

연관된 Markdown 파일 그룹이 있는 경우 [컬렉션으로 정의](/ko/guides/content-collections/)하는 것을 고려해 보세요. 이렇게 하면 파일 시스템의 어느 곳에나 또는 원격으로 Markdown 파일을 저장할 수 있는 등 여러 가지 이점이 있습니다.

컬렉션은 파일 가져오기 대신 [Markdown 콘텐츠를 쿼리하고 렌더링](#콘텐츠-컬렉션-쿼리의-markdown)하기 위해 콘텐츠별 최적화된 API를 사용합니다. 컬렉션은 블로그 게시물이나 제품 항목과 같이 동일한 구조를 공유하는 데이터 집합을 위한 것입니다. 스키마에서 해당 형태를 정의하면 편집기에서 유효성 검사, 타입 안전, 인텔리센스를 사용할 수 있습니다.

<ReadMore>파일 가져오기 대신 [콘텐츠 컬렉션을 사용하는 경우](/ko/guides/content-collections/#컬렉션-생성이-필요한-경우)에 대해 자세히 알아보세요.</ReadMore>

## 동적 JSX 유사 표현식

Markdown 파일을 가져오거나 쿼리한 후에는 프런트매터 데이터와 본문 콘텐츠를 포함하는 `.astro` 컴포넌트에 동적 HTML 템플릿을 작성할 수 있습니다.

```md title="src/pages/posts/great-post.md"
---
title: 'The greatest post of all time'
author: 'Ben'
---

Here is my _great_ post!
```

```astro title="src/pages/my-posts.astro"
---
import * as greatPost from './posts/great-post.md';
const posts = Object.values(import.meta.glob('./posts/*.md', { eager: true }));
---

<p>{greatPost.frontmatter.title}</p>
<p>Written by: {greatPost.frontmatter.author}</p>

<p>Post Archive:</p>
<ul>
  {posts.map(post => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
</ul>
```

### 사용 가능한 속성

#### 콘텐츠 컬렉션 쿼리의 Markdown

헬퍼 함수 `getCollection()` 또는 `getEntry()`를 사용하여 컬렉션에서 데이터를 가져올 때, Markdown의 프런트매터 속성은 `data` 객체(예: `post.data.title`)에서 사용할 수 있습니다. 또한 `body`는 원시 형태의 컴파일되지 않은 본문 내용을 문자열로 포함합니다.

[`render()`](/ko/reference/modules/astro-content/#render) 함수는 Markdown 본문 내용, 생성된 제목 목록, 그리고 remark나 rehype 플러그인이 적용된 후의 수정된 프런트매터 객체를 반환합니다.

<ReadMore>[컬렉션 쿼리에서 반환된 콘텐츠 사용하기](/ko/guides/content-collections/#astro-템플릿에서-콘텐츠-사용)에 대해 자세히 알아보세요.</ReadMore>

#### Markdown 가져오기

`import` 또는 `import.meta.glob()`을 사용하여 Markdown을 가져올 때 내보낸 다음 속성은 `.astro` 컴포넌트에서 사용할 수 있습니다:

- **`file`** - 절대 파일 경로 (예: `/home/user/projects/.../file.md`).
- **`url`** - 페이지의 URL (예: `/en/guides/markdown-content`).
- **`frontmatter`** - 파일의 YAML (또는 TOML) 프런트매터에 지정된 모든 데이터를 포함합니다.
- **`<Content />`** - 파일의 전체 렌더링된 콘텐츠를 반환하는 컴포넌트입니다.
- **`rawContent()`** - 원시 Markdown 문서를 문자열로 반환하는 함수입니다.
- **`compiledContent()`** - HTML 문자열로 컴파일된 Markdown 문서를 반환하는 비동기 함수입니다.
- **`getHeadings()`** - `{ depth: number; slug: string; text: string }[]` 타입을 가지는 파일의 모든 제목 (예: `<h1>`부터 `<h6>`)의 배열을 반환하는 비동기 함수입니다. 각 제목의 `slug`는 특정 제목에 대해 생성된 ID에 해당하며, 앵커 링크에 사용될 수 있습니다.

Markdown 블로그 게시물 예시에서는 다음 `Astro.props` 객체를 전달할 수 있습니다:

```js
Astro.props = {
  file: "/home/user/projects/.../file.md",
  url: "/en/guides/markdown-content/",
  frontmatter: {
    /** 블로그 게시물의 프런트매터 */
    title: "Astro 0.18 Release",
    date: "Tuesday, July 27 2021",
    author: "Matthew Phillips",
    description: "Astro 0.18 is our biggest release since Astro launch.",
  },
  getHeadings: () => [
    {"depth": 1, "text": "Astro 0.18 Release", "slug": "astro-018-release"},
    {"depth": 2, "text": "Responsive partial hydration", "slug": "responsive-partial-hydration"}
    /* ... */
  ],
  rawContent: () => "# Astro 0.18 Release\nA little over a month ago, the first public beta [...]",
  compiledContent: () => "<h1>Astro 0.18 Release</h1>\n<p>A little over a month ago, the first public beta [...]</p>",
}
```

## `<Content />` 컴포넌트

`<Content />` 컴포넌트는 Markdown 파일에서 `Content`를 가져와서 사용할 수 있습니다. 이 컴포넌트는 파일의 전체 본문 콘텐츠를 HTML로 렌더링하여 반환합니다. 선택적으로 `Content`의 이름을 원하는 컴포넌트 이름으로 변경할 수 있습니다.

이와 유사하게 `<Content />` 컴포넌트를 렌더링하여 [Markdown 컬렉션 항목의 HTML 콘텐츠를 렌더링](/ko/guides/content-collections/#본문-콘텐츠-렌더링)을 할 수 있습니다.

```astro title="src/pages/content.astro" "Content"
---
// 가져오기 문
import {Content as PromoBanner} from '../components/promoBanner.md';

// 컬렉션 쿼리
import { getEntry, render } from 'astro:content';
const product = await getEntry('products', 'shirt');
const { Content } = await render(product);
---
<h2>Today's promo</h2>
<PromoBanner />

<p>Sale Ends: {product.data.saleEndDate.toDateString()}</p>
<Content />
```

## 제목 ID

Markdown으로 제목을 작성하면 자동으로 앵커 링크가 제공되므로 페이지의 특정 섹션으로 바로 연결할 수 있습니다. Astro는 ASCII가 아닌 콘텐츠를 쉽게 작성할 수 있도록 페이지에 `<meta charset="utf-8">` 태그를 자동으로 추가합니다.

```markdown title="src/pages/page-1.md"
---
title: My page of content
---
## Introduction

I can link internally to [my conclusion](#conclusion) on the same page when writing Markdown.

## Conclusion

I can visit `https://example.com/page-1/#introduction` in a browser to navigate directly to my Introduction.
```

Astro는 `github-slugger`를 기반으로 제목의 `id`를 생성합니다. 더 많은 예시는 [github-slugger 문서](https://github.com/Flet/github-slugger#usage)에서 찾을 수 있습니다.

### 제목 ID와 플러그인

Astro는 Markdown과 MDX 파일의 모든 제목 요소(`<h1>`부터 `<h6>`)에 `id` 속성을 주입합니다. 이 데이터는 가져온 파일의 [Markdown 내보내기 속성](#사용-가능한-속성)으로 제공되는 `getHeadings()` 유틸리티를 통해, 또는 [콘텐츠 컬렉션 쿼리에서 반환된 Markdown을 사용할 때](#콘텐츠-컬렉션-쿼리의-markdown)는 `render()` 함수를 통해 가져올 수 있습니다.

`id` 속성 (예: `rehype-slug`)을 삽입하는 rehype 플러그인을 추가하여 이러한 제목 ID를 맞춤설정할 수 있습니다. Astro의 기본값 대신 사용자 정의 ID가 HTML 출력과 `getHeadings()`에 의해 반환된 항목에 반영됩니다.

기본적으로 Astro는 rehype 플러그인이 실행된 후 `id` 속성을 주입합니다. 사용자 정의 rehype 플러그인 중 하나가 Astro에서 삽입한 ID에 액세스해야 하는 경우 Astro의 `rehypeHeadingIds` 플러그인을 직접 가져와 사용할 수 있습니다. 이를 사용하는 플러그인 앞에 `rehypeHeadingIds`를 추가하세요.

```js title="astro.config.mjs" ins={2, 8}
import { defineConfig } from 'astro/config';
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import { otherPluginThatReliesOnHeadingIDs } from 'some/plugin/source';

export default defineConfig({
  markdown: {
    rehypePlugins: [
      rehypeHeadingIds,
      otherPluginThatReliesOnHeadingIDs,
    ],
  },
});
```

## Markdown 플러그인

Astro의 Markdown 지원은 활성 생태계를 갖춘 강력한 구문 분석 및 처리 도구인 [remark](https://remark.js.org/)를 통해 제공됩니다. Pandoc 및 markdown-it과 같은 다른 Markdown 파서는 현재 지원되지 않습니다.

Astro는 기본적으로 [GitHub-flavored Markdown](https://github.com/remarkjs/remark-gfm) 및 [SmartyPants](https://github.com/silvenon/remark-smartypants) 플러그인을 적용합니다. 이는 텍스트에서 클릭 가능한 링크 생성, [인용 및 em-dashes](https://daringfireball.net/projects/smartypants/) 서식 지정과 같은 몇 가지 장점을 제공합니다.

`astro.config.mjs` 파일에서 remark가 Markdown을 구문 분석하는 방법을 사용자 정의할 수 있습니다. [Markdown 구성 옵션](/ko/reference/configuration-reference/#markdown-옵션)의 전체 목록을 확인하세요.

### remark 및 rehype 플러그인 추가하기

Astro는 Markdown에 대한 타사 [remark](https://github.com/remarkjs/remark) 및 [rehype](https://github.com/rehypejs/rehype) 플러그인 추가를 지원합니다. 이러한 플러그인을 사용하면 [목차 자동 생성](https://github.com/remarkjs/remark-toc), [접근 가능한 이모티콘 라벨 적용](https://github.com/florianeckerstorfer/remark-a11y-emoji), [Markdown 스타일 지정](/ko/guides/styling/#markdown-스타일링)과 같은 새로운 기능으로 Markdown을 확장할 수 있습니다.

[awesome-remark](https://github.com/remarkjs/awesome-remark) 및 [awesome-rehype](https://github.com/rehypejs/awesome-rehype)와 같은 인기 플러그인들을 찾아보시기 바랍니다! 구체적인 설치 지침은 각 플러그인의 자체 README를 참조하세요.

이 예시에서는 Markdown 파일에 [`remark-toc`](https://github.com/remarkjs/remark-toc) 및 [`rehype-accessible-emojis`](https://www.npmjs.com/package/rehype-accessible-emojis)를 적용합니다.

```js title="astro.config.mjs"
import { defineConfig } from 'astro/config';
import remarkToc from 'remark-toc';
import { rehypeAccessibleEmojis } from 'rehype-accessible-emojis';

export default defineConfig({
  markdown: {
    // .md 및 .mdx 파일에 적용됨
    remarkPlugins: [ [remarkToc, { heading: 'toc', maxDepth: 3 } ] ],
    rehypePlugins: [rehypeAccessibleEmojis],
  },
});
```

### 플러그인 사용자 정의

플러그인을 사용자 정의하려면 중첩 배열에서 플러그인 뒤에 옵션 객체를 제공하세요.

아래 예시에서는 [`remarkToc` 플러그인에 heading 옵션을 추가](https://github.com/remarkjs/remark-toc#options)하여 목차 위치를 변경하고, [`rehype-autolink-headings` 플러그인에 `behavior` 옵션을 추가](https://github.com/rehypejs/rehype-autolink-headings#options)하여 제목 텍스트 뒤에 앵커 태그를 추가했습니다.

```js title="astro.config.mjs"
import remarkToc from 'remark-toc';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';

export default {
  markdown: {
    remarkPlugins: [ [remarkToc, { heading: "contents"} ] ],
    rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'append' }]],
  },
}
```

### 프로그래밍 방식으로 프런트매터 수정하기

[remark 또는 rehype 플러그인](#markdown-플러그인)을 사용하여 모든 Markdown 및 MDX 파일에 프런트매터 속성을 추가할 수 있습니다.

<Steps>
1. 플러그인의 `file` 인수에서 `data.astro.frontmatter` 속성에 `customProperty`를 추가합니다.

    ```js title="example-remark-plugin.mjs"
    export function exampleRemarkPlugin() {
      // 모든 remark 및 rehype 플러그인은 별도의 함수를 반환합니다.
      return function (tree, file) {
        file.data.astro.frontmatter.customProperty = 'Generated property';
      }
    }
    ```

    :::tip
    <Since v="2.0.0" />

    `data.astro.frontmatter`에는 특정 Markdown 또는 MDX 문서의 모든 속성이 포함되어 있습니다. 이를 통해 기존 프런트매터 속성을 수정하거나 기존 프런트매터에서 새 속성을 계산할 수 있습니다.
    :::

2. 이 플러그인을 `markdown` 또는 `mdx` 통합 구성에 적용하세요.

    ```js title="astro.config.mjs" "import { exampleRemarkPlugin } from './example-remark-plugin.mjs';" "remarkPlugins: [exampleRemarkPlugin],"
    import { defineConfig } from 'astro/config';
    import { exampleRemarkPlugin } from './example-remark-plugin.mjs';

    export default defineConfig({
      markdown: {
        remarkPlugins: [exampleRemarkPlugin]
      },
    });
    ```

    또는

    ```js title="astro.config.mjs" "import { exampleRemarkPlugin } from './example-remark-plugin.mjs';" "remarkPlugins: [exampleRemarkPlugin],"
    import { defineConfig } from 'astro/config';
    import { exampleRemarkPlugin } from './example-remark-plugin.mjs';

    export default defineConfig({
      integrations: [
        mdx({
          remarkPlugins: [exampleRemarkPlugin],
        }),
      ],
    });
    ```
</Steps>

이제 모든 Markdown 또는 MDX 파일의 프런트매터에 `customProperty`가 있으므로 [Markdown을 가져올 때](#markdown-가져오기) [레이아웃의 `Astro.props.frontmatter` 속성](#프런트매터-layout-속성)에서 사용할 수 있습니다.

<RecipeLinks slugs={["ko/recipes/reading-time"]} />

### MDX에서 Markdown 구성 확장

Astro의 MDX 통합은 기본적으로 [프로젝트의 기존 Markdown 구성](/ko/reference/configuration-reference/#markdown-옵션)을 확장합니다. 개별 옵션을 재정의하려면 MDX 구성에서 해당 옵션을 지정하면 됩니다.

다음 예시에서는 GitHub 기반 Markdown을 비활성화하고 MDX 파일에 대해 다른 remark 플러그인 세트를 적용합니다.

```ts title="astro.config.mjs"
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

export default defineConfig({
  markdown: {
    syntaxHighlight: 'prism',
    remarkPlugins: [remarkPlugin1],
    gfm: true,
  },
  integrations: [
    mdx({
      // Markdown에서 상속된 `syntaxHighlight`

      // Markdown `remarkPlugins`가 무시되었습니다.
      // `remarkPlugin2`만 적용됩니다.
      remarkPlugins: [remarkPlugin2],
      // `gfm`이 `false`로 재정의됨
      gfm: false,
    })
  ]
});
```

MDX에서 Markdown 구성을 확장하지 않으려면 [`extendMarkdownConfig` 옵션](/ko/guides/integrations-guide/mdx/#extendmarkdownconfig) (기본적으로 활성화됨)을 `false`로 설정하세요.

```ts title="astro.config.mjs"
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

export default defineConfig({
  markdown: {
    remarkPlugins: [remarkPlugin],
  },
  integrations: [
    mdx({
      // Markdown 구성은 이제 무시됩니다.
      extendMarkdownConfig: false,
      // 'remarkPlugins'가 적용되지 않았습니다.
    })
  ]
});
```

## 개별 Markdown 페이지

:::tip
[콘텐츠 컬렉션](/ko/guides/content-collections/)과 [Markdown을 `.astro` 컴포넌트로 가져오기](#동적-jsx-유사-표현식)는 Markdown 렌더링에 더 많은 기능을 제공하며, 대부분의 콘텐츠를 처리하는 데 권장되는 방식입니다. 하지만 `src/pages/`에 파일을 추가하기만 하면 간단한 페이지가 자동으로 생성되는 편리함을 원할 때가 있습니다.
:::

Astro는 `.md` 및 기타 Markdown 파일 유형을 포함하여 [`/src/pages/` 디렉터리 내 지원되는 모든 파일](/ko/basics/astro-pages/#지원되는-페이지-파일)을 페이지로 취급합니다.

이 디렉터리 또는 하위 디렉터리에 파일을 배치하면 파일 경로명을 사용하여 페이지 경로를 자동으로 빌드하고 HTML로 렌더링된 Markdown 콘텐츠가 표시됩니다.

```markdown title="src/pages/page-1.md"
---
title: Hello, World
---

# Hi there!

This Markdown file creates a page at `your-domain.com/page-1/`

It probably isn't styled much, but Markdown does support:
- **bold** and _italics._
- lists
- [links](https://astro.build)
- <p>HTML elements</p>
- and more!
```

### 프런트매터 `layout` 속성

개별 Markdown 페이지의 제한된 기능을 보완하기 위해, Astro는 [Markdown 레이아웃 컴포넌트](/ko/basics/layouts/#markdown-레이아웃)에 대한 상대 경로를 가진 특별한 프런트매터 `layout` 속성을 제공합니다. `layout`은 [콘텐츠 컬렉션](/ko/guides/content-collections/)을 사용하여 Markdown 콘텐츠를 쿼리하고 렌더링할 때는 특별한 속성이 아니며, 의도된 사용 사례를 벗어나면 지원이 보장되지 않습니다.

만약 Markdown 파일이 `src/pages/`에 위치해 있다면, 레이아웃 컴포넌트를 생성하고 이를 layout 속성에 추가하여 Markdown 콘텐츠 주위에 페이지 셸을 제공하세요.

```markdown title="src/pages/posts/post-1.md" {2}
---
layout: ../../layouts/BlogPostLayout.astro
title: Astro in brief
author: Himanshu
description: Find out what makes Astro awesome!
---
This is a post written in Markdown.
```

이 레이아웃 컴포넌트는 Astro 템플릿의 `Astro.props`를 통해 [특정 속성을 자동으로 사용할 수 있는](/ko/basics/layouts/#markdown-레이아웃-props) 일반 Astro 컴포넌트입니다. 예를 들어, `Astro.props.frontmatter`를 통해 Markdown 파일의 프런트매터 속성에 액세스할 수 있습니다:

```astro title="src/layouts/BlogPostLayout.astro" /frontmatter(?:.\w+)?/
---
const {frontmatter} = Astro.props;
---
<html>
  <head>
    <!-- ... -->
    <meta charset="utf-8"> // 기본적으로 더 이상 추가되지 않습니다.
  </head>
  <!-- ... -->
  <h1>{frontmatter.title}</h1>
  <h2>Post author: {frontmatter.author}</h2>
  <p>{frontmatter.description}</p>
  <slot /> <!-- Markdown content is injected here -->
  <!-- ... -->
</html>
```

프런트매터 `layout` 속성을 사용할 때는 Astro가 더 이상 자동으로 추가하지 않으므로 레이아웃에 `<meta charset="utf-8">` 태그를 포함해야 합니다. 이제 레이아웃 컴포넌트에서 [Markdown을 스타일링](/ko/guides/styling/#markdown-스타일링)할 수도 있습니다.

<ReadMore>[Markdown 레이아웃](/ko/basics/layouts/#markdown-레이아웃)에 대해 더 자세히 알아보세요.</ReadMore>

## 원격 Markdown 가져오기

Astro의 내장 Markdown 프로세서는 원격 Markdown 처리에 사용할 수 없습니다.

[콘텐츠 컬렉션](/ko/guides/content-collections/)에서 사용하기 위해 원격 Markdown을 가져오려면, [`renderMarkdown()` 함수](/ko/reference/content-loader-reference/#rendermarkdown)에 접근할 수 있는 [사용자 정의 로더](/ko/guides/content-collections/#컬렉션-loader-정의)를 구축할 수 있습니다.

원격 Markdown을 직접 가져와 HTML로 렌더링하려면 NPM에서 자체 Markdown 파서를 설치 및 구성해야 합니다. 이렇게 하면 사용자가 구성한 Astro의 기본 제공 Markdown 설정이 상속되지 **않습니다**.

이를 프로젝트에서 구현하기 전에 이러한 제한 사항을 이해하고, 대신 콘텐츠 컬렉션 로더를 사용하여 원격 Markdown을 가져오는 것을 고려하세요.

```astro title="src/pages/remote-example.astro"
---
// 예: 원격 API에서 Markdown 가져오기
// 런타임에 HTML로 렌더링합니다.
// "marked" 사용 (https://github.com/markedjs/marked)
import { marked } from 'marked';
const response = await fetch('https://raw.githubusercontent.com/wiki/adam-p/markdown-here/Markdown-Cheatsheet.md');
const markdown = await response.text();
const content = marked.parse(markdown);
---
<article set:html={content} />
```
